package com.panda.pojo;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.panda.utils.IdUtils;
import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Setter
@Getter
public class Element extends Block {


    //是否是重复的
    private boolean repetitive = false;

    protected List<Block> subBlocks;

    private Element lastSubElement;

    protected Context context;

    //设置上下文
    public void setContext(Context context) {//应该会移除掉Context

        this.context = context;

        if (subBlocks != null) {
            for (Block block : subBlocks) {

                if (block instanceof Element) {
                    ((Element) block).setContext(context);
                }

            }
        }

    }

    public Element find(String name) {

        if (this.name.equals(name)) {
            return this;
        }


        if (subBlocks == null) {
            return null;
        }

        for (Block subBlock : subBlocks) {

            if (subBlock instanceof Element) {

                Element element = ((Element) subBlock).find(name);

                if (element != null) {
                    return element;
                }

            }

        }

        return null;


    }

    public Element take(String name) {
        if (this.name.equals(name)) {
            //把自己从父组件中移除
            parent.getSubBlocks().remove(this);
            return this;
        }


        if (subBlocks == null) {
            return null;
        }

        for (Block subBlock : subBlocks) {

            if (subBlock instanceof Element) {

                Element element = ((Element) subBlock).take(name);

                if (element != null) {
                    return element;
                }

            }

        }

        return null;

    }

    public void handleDep() {

        Set<String> dependencies = scope.getDependencies();

        //如果有脚本
        if (scope.getScript() != null && !scope.getScript().equals("")) {

            attributes.put("eid", id);

            //添加作用域
            context.getControllerScopes().add(scope);

        }

        Map<String, Service> serviceMap = context.getServiceMap();

        if (serviceMap != null) {

            Set<Service> services = context.getServices();

            Set<String> contextJs = context.getJs();

            Set<String> contextCss = context.getCss();

            dependencies.forEach(s -> {

                Service service = serviceMap.get(s);

                if (service != null) {

                    services.add(service);

                    Set<String> serviceDependencies = service.getDependencies();

                    if (serviceDependencies != null) {

                        serviceDependencies.forEach(s1 -> {

                            Service service1 = serviceMap.get(s1);

                            if (service1 != null) {
                                services.add(service1);
                            }

                        });

                    }

                    Set<String> js = service.getJs();

                    if (js != null) {
                        contextJs.addAll(js);
                    }


                    Set<String> css = service.getCss();

                    if (css != null) {
                        contextCss.addAll(css);
                    }


                }

            });
        }


        if (subBlocks != null) {

            for (Block block : subBlocks) {
                if (block instanceof Element) {

                    ((Element) block).handleDep();

                }
            }
        }

    }


    //属性
    protected Map<String, String> attributes = new HashMap<>();

    private Scope scope;

    @JsonIgnore
    private Element parent;

    @JsonIgnore
    private boolean assigning = false;

    protected String name;

    @JsonIgnore
    private boolean hasParsed = false;

    //新建一个元素的时候期望小括号输入属性.当属性输入完后期望输入大括号,当大括号结束后变为-1不期望任何内容
    @JsonIgnore
    private int expect;

    @JsonIgnore
    private boolean inputArrt = false;

    public static final int BTP = 1;

    public static final int BTB = 2;

    //期望输入大括号中的文本
    public static final int BTTmp = 3;

    @JsonIgnore
    private int tlbn = 0;

    @JsonIgnore
    private int tlpn = 0;


    @JsonIgnore
    private String bodyText;

    @JsonIgnore
    private String paramsText;

    @JsonIgnore
    private StringBuilder bufferedText = new StringBuilder();

    public Element appendTempText(String text) {
        bufferedText.append(text);
        return this;
    }


    //添加子元素
    public void addSubBlock(Block block) {

        subBlocks.add(block);

        if (block instanceof Element) {
            ((Element) block).setParent(this);
            ((Element) block).getScope().setParent(this.getScope());
        }
    }

    public Element() {
    }

    //元素名称  div  body 等等
    public Element(Context context, String name) {
        this.context = context;
        this.name = name;
        id = IdUtils.create(context, "__element_");
        scope = new Scope(this);
    }

    @JsonIgnore
    private Set<String> protectedStrings;

    @Override
    public String toString() {


        //首字母小写处理
        String name = this.name.substring(0, 1).toLowerCase() + this.name.substring(1);

        StringBuilder builder = new StringBuilder("<" + name);

        Map<String, String> stringMap = context.getStringMap();

        attributes.forEach((k, v) -> {

            if (v == null) {
                builder.append(" ").append(k);
            } else {

                //交给组件自行展开
                if (stringMap.containsKey(v) || v.startsWith("__string_temp_")) {
                    builder.append(" ").append(k).append("=").append(v);
                } else {
                    builder.append(" ").append(k).append("=").append("\"").append(v).append("\"");
                }

            }


        });


        builder.append(">").append("\n");

        if (subBlocks != null) {

            //递归操作
            for (Block aSubElement : subBlocks) {
                builder.append(aSubElement.toString());
            }

            builder.append("</").append(name).append(">").append("\n");

        }


        return builder.toString();

    }


}

